<?php
/**
 * 点大商城（www.diandashop.com） - 微信公众号小程序商城系统!
 * Copyright © 2020 山东点大网络科技有限公司 保留所有权利
 * =========================================================
 * 版本：V2
 * 授权主体：海南芒点网络科技有限公司
 * 授权域名：kf.hnmangdian.com
 * 授权码：iuGYepyTlKxWomKwhgsupaLmF
 * ----------------------------------------------
 * 您只能在商业授权范围内使用，不可二次转售、分发、分享、传播
 * 任何企业和个人不得对代码以任何目的任何形式的再发布
 * =========================================================
 */

// +----------------------------------------------------------------------
// | 公众号支付设置
// +----------------------------------------------------------------------
namespace app\controller;
use think\facade\View;
use think\facade\Db;

use WeChatPay\Crypto\Rsa;
use WeChatPay\Util\PemUtil;
use WeChatPay\Crypto\AesGcm;
use WeChatPay\Formatter;

class Wxpay extends Common
{
    public function initialize(){
		parent::initialize();
		if(bid > 0) showmsg('无访问权限');
	}
	//公众号支付设置
    public function set(){
		if(request()->isPost()){
			$info = input('post.info/a');
			$rs = Db::name('admin_setapp_wx')->where('aid',aid)->find();
			$info['wxpay_mchid'] = trim($info['wxpay_mchid']);
			$info['wxpay_mchkey'] = trim($info['wxpay_mchkey']);
			$info['wxpay_sub_mchid'] = trim($info['wxpay_sub_mchid']);
			$info['wxpay_apiclient_cert'] = str_replace(PRE_URL.'/','',$info['wxpay_apiclient_cert']);
			$info['wxpay_apiclient_key'] = str_replace(PRE_URL.'/','',$info['wxpay_apiclient_key']);
            $info['wxpay_wechatpay_pem'] = str_replace(PRE_URL.'/','',$info['wxpay_wechatpay_pem']);
			if(!empty($info['wxpay_apiclient_cert']) && substr($info['wxpay_apiclient_cert'], -4) != '.pem'){
				return json(['status'=>0,'msg'=>'PEM证书格式错误']);
			}
			if(!empty($info['wxpay_apiclient_key']) && substr($info['wxpay_apiclient_key'], -4) != '.pem'){
				return json(['status'=>0,'msg'=>'证书密钥格式错误']);
			}
            if(!empty($info['wxpay_wechatpay_pem']) && substr($info['wxpay_wechatpay_pem'], -4) != '.pem'){
                return json(['status'=>0,'msg'=>'平台证书格式错误']);
            }
            //支付公钥
            $info['sign_type'] = $info['sign_type'];
            $info['public_key_id'] = trim($info['public_key_id']);
            $info['public_key_pem'] = str_replace(PRE_URL.'/','',$info['public_key_pem']);

			$info['sxpay_mno'] = trim($info['sxpay_mno']);
            $info['transfer_scene_id'] = trim($info['transfer_scene_id']);
            $info['transfer_scene_type'] = trim($info['transfer_scene_type']);
            $info['transfer_scene_content'] = trim($info['transfer_scene_content']);

            Db::name('admin_setapp_wx')->where('aid',aid)->update($info);
			\app\common\System::plog('微信小程序支付设置');
			return json(['status'=>1,'msg'=>'设置成功','url'=>true]);
		}
		$info = Db::name('admin_setapp_wx')->where('aid',aid)->find();
		if(!$info) Db::name('admin_setapp_wx')->insert(['aid'=>aid]);
		View::assign('info',$info);
        //随行付进件状态
        $incomeStatus = \app\custom\Sxpay::getIncomeStatus(aid);
        View::assign('incomeStatus',$incomeStatus);

        $currencys= $this->currency();
        View::assign('currencys',$currencys);
		return View::fetch();
	}
	// 海外版支持货币类型
	public function currency(){
		$arr = [
			'HKD'=>	'港币',
			'SGD'=>	'新加坡元',
			'MYR'=>	'马来西亚林吉特',
			'THB'=>	'泰铢',
			'JPY'=>	'日元',
			'AUD'=>	'澳元',
			'CAD'=>	'加元',
			'EUR'=>	'欧元',
			'GBP'=>	'英镑',
			'USD'=>	'美元',
		];
		return $arr;
	}
	
	//下载海外微信V3支付用的平台证书
    public function download_pem(){
    	$appinfo = \app\common\System::appinfo(aid,'wx');
    	
    	$apiv3Key = $appinfo['wxpay_mchkey_global'];// APIv3密钥
    	$merchantPrivateKeyFilePath = ROOT_PATH.$appinfo['wxpay_apiclient_key_global'];
		$merchantId = $appinfo['wxpay_mchid_global'];
		$method = 'GET';
		$uri = '/v3/global/certificates';
		$merchantCertificateSerial = $appinfo['wxpay_serial_no_global'];
		$merchantPrivateKeyFileContent = file_get_contents($merchantPrivateKeyFilePath);
		$merchantPrivateKey = Rsa::from($merchantPrivateKeyFileContent, Rsa::KEY_TYPE_PRIVATE);

		// 签名
		$auth = \app\common\WxpayGlobal::authorization($merchantId, $merchantPrivateKey, $merchantCertificateSerial, $method, $uri);
// 		dump($auth);
		$headers = [
		   "Content-Type: application/json;charset='utf-8'",
		    "Accept: application/json",
		    "User-Agent:".$_SERVER['HTTP_USER_AGENT'],
			"Authorization: ".$auth
		];
		$url = 'https://apihk.mch.weixin.qq.com/v3/global/certificates';
		$param = [];
// 		$res = curl_get($url,$param,$headers);
  		
  		try {
            $response = $this->curl_get_with_headers($url, $param, $headers);
            
            // 处理响应头
            $headers_array = [];
            foreach (explode("\r\n", $response['headers']) as $header_line) {
                if (strpos($header_line, ':') !== false) {
                    list($key, $value) = explode(':', $header_line, 2);
                    $headers_array[trim($key)] = trim($value);
                }
            }
            
            // 处理响应体
            // $data = json_decode($response['body'], true);
            // dump($headers_array);
            
            $inWechatpaySignature = $headers_array['Wechatpay-Signature'];// Get this value from the header in response
            $inWechatpayTimestamp = $headers_array['Wechatpay-Timestamp'];// Get this value from the header in response
            $inWechatpaySerial = $headers_array['Wechatpay-Serial'];// Get this value from the header in response
            $inWechatpayNonce = $headers_array['Wechatpay-Nonce'];// Get this value from the header in response
            $inBody = $response['body'];// Get this value from the body in response
            $platformPublicKeyFilePath = ROOT_PATH.$appinfo['wxpay_wechatpay_pem_global'];
            $platformPublicKeyFileContent = file_get_contents($platformPublicKeyFilePath);
            $platformPublicKeyInstance = Rsa::from($platformPublicKeyFileContent, Rsa::KEY_TYPE_PUBLIC);
            // dump(Formatter::timestamp());dump(date('Y-m-d H:i'));dump($inWechatpayTimestamp);die;
            // dump('签名字符串'.Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody));die;
            
            
            // dump($inWechatpayTimestamp);dump($inWechatpayNonce);dump($inBody);dump($inWechatpaySignature);dump($platformPublicKeyInstance);dump(11111);die;
            $timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp);
            $verifiedStatus = Rsa::verify(
                Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody),
                $inWechatpaySignature,
                $platformPublicKeyInstance
            );
            // dump($timeOffsetStatus);dump($verifiedStatus);die;
            if ($timeOffsetStatus && $verifiedStatus) {
                $inBodyArray = (array)json_decode($inBody, true);
                ['resource' => [
                    'ciphertext'      => $ciphertext,
                    'nonce'           => $nonce,
                    'associated_data' => $aad
                ]] = $inBodyArray;
                $inBodyResource = AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad);
                $inBodyResourceArray = (array)json_decode($inBodyResource, true);

                // 保存证书
                $out_path = ROOT_PATH.'upload'.DIRECTORY_SEPARATOR.aid.DIRECTORY_SEPARATOR.'wechatkeyglobal'.DIRECTORY_SEPARATOR;
                $filename = $out_path . 'wechatkeyglobal_'.aid.'.pem';
                if(!file_exists($out_path)){
                    mk_dir($out_path, 0775);
                }
                
                if (file_put_contents($filename, $inBodyResourceArray)) {
                    return ['status'=>1, 'data'=>$filename, 'msg'=>'下载成功'];
                } else {
                    return ['status'=>0,'msg'=>'下载失败'];
                }
            }
            
        } catch (Exception $e) {
            die("请求出错: " . $e->getMessage()) ;
        }
  		


    }
    
    function curl_get_with_headers($url, $params = [], $headers = []) {
        $ch = curl_init();
        
        // 设置基本 cURL 选项
        curl_setopt($ch, CURLOPT_URL, $url . (empty($params) ? '' : '?' . http_build_query($params)));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        
        // 关键设置：获取响应头
        curl_setopt($ch, CURLOPT_HEADER, true);  // 包含头信息在输出中
        
        $response = curl_exec($ch);
        
        if ($response === false) {
            $error = curl_error($ch);
            curl_close($ch);
            die("cURL 请求失败: " . $error);
        }
        
        // 分离响应头和响应体
        $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
        $response_headers = substr($response, 0, $header_size);
        $response_body = substr($response, $header_size);
        
        curl_close($ch);
        
        return [
            'headers' => $response_headers,
            'body' => $response_body
        ];
    }

	//下载海外微信V3支付用的平台证书
    public function download_pemtest(){
    	// $rs = curl_get('https://apihk.mch.weixin.qq.com/v3/global/certificates');
    	// dump($rs);die;
    	$appinfo = \app\common\System::appinfo(aid,'wx');

		$mchid = $appinfo['wxpay_mchid_global'];                          // 商户号
		$api_v3_key = $appinfo['wxpay_mchkey_global'];                // APIv3密钥
		$private_key = file_get_contents(ROOT_PATH.$appinfo['wxpay_apiclient_key_global']); // 商户私钥
		$serial_no = $appinfo['wxpay_serial_no_global']; // 证书序列号

		// 1. 构造请求并签名
		$url = 'https://apihk.mch.weixin.qq.com/v3/global/certificates';
		$timestamp = time();
		$nonce = bin2hex(random_bytes(8));
		$body = ''; // GET 请求无 Body
		
// 		dump($mchid);dump($api_v3_key);dump($private_key);dump($serial_no);die;
		// 确保 APIv3 密钥是 32 字节的字符串
        if (strlen($api_v3_key) != 32) {
            die("APIv3 密钥长度不正确，应为 32 字节");
        }

		// 构造签名串
		$message = "GET\n/v3/global/certificates\n{$timestamp}\n{$nonce}\n{$body}\n";
		openssl_sign($message, $signature, $private_key, OPENSSL_ALGO_SHA256);
		$signature_base64 = base64_encode($signature);

		// 构造 Authorization
		$auth = sprintf(
		    'WECHATPAY2-SHA256-RSA2048 mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
		    $mchid,
		    $nonce,
		    $timestamp,
		    $serial_no,
		    $signature_base64
		);

		// 2. 发送请求
		$ch = curl_init();
		curl_setopt_array($ch, [
		    CURLOPT_URL => $url,
		    CURLOPT_RETURNTRANSFER => true,
		    CURLOPT_HTTPHEADER => [
		        'Accept: application/json',
		        'User-Agent:'.$_SERVER['HTTP_USER_AGENT'],
		        'Authorization: ' . $auth,
		    ],
		]);

		$response = curl_exec($ch);
		$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
		curl_close($ch);

		if ($httpCode !== 200) {
		    die("请求失败: HTTP {$httpCode}\n响应: {$response}");
		}

// 		3. 解析并解密证书
		$data = json_decode($response, true);

		if (json_last_error() !== JSON_ERROR_NONE) {
		    die("JSON 解析失败: " . json_last_error_msg());
		}
		foreach ($data['data'] as $cert) {
            $ciphertext = base64_decode($cert['encrypt_certificate']['ciphertext']);
            $nonce = $cert['encrypt_certificate']['nonce'];
            $associated_data = $cert['encrypt_certificate']['associated_data'] ?? '';
            
            // 使用 AEAD_AES_256_GCM 解密
            $cert_pem = openssl_decrypt(
                $ciphertext,
                'aes-256-gcm',
                $api_v3_key,
                OPENSSL_RAW_DATA,
                $nonce,
                $associated_data
            );
            
            if ($cert_pem === false) {
                die("解密失败: " . openssl_error_string());
            }
        
            // 确保是有效的 PEM 格式
            if (strpos($cert_pem, '-----BEGIN CERTIFICATE-----') === false) {
                $cert_pem = "-----BEGIN CERTIFICATE-----\n" . 
                            chunk_split(base64_encode($cert_pem), 64, "\n") . 
                            "-----END CERTIFICATE-----\n";
            }
        
            // 保存证书
            $out_path = ROOT_PATH.'upload'.DIRECTORY_SEPARATOR.aid.DIRECTORY_SEPARATOR.'wechatkeyglobal'.DIRECTORY_SEPARATOR;
            $filename = $out_path . 'wechatkeyglobal_'.aid.'.pem';
            if(!file_exists($out_path)){
                mk_dir($out_path, 0775);
            }
            
            if (file_put_contents($filename, $cert_pem)) {
                return ['status'=>1, 'data'=>$filename, 'msg'=>'下载成功'];
            } else {
                return ['status'=>0,'msg'=>'下载失败'];
            }
        }  
    }

}